#!/usr/bin/env python
# carlos@lacnic.net 20111220
#===============================================================================
# Copyright (c) 2011 LACNIC - Latin American and Caribbean Internet 
# Address Registry
# 
# Permission is hereby granted, free of charge, to any person 
# obtaining a copy of this software and associated documentation 
# files (the "Software"), to deal in the Software without 
# restriction, including without limitation the rights to use, copy, 
# modify, merge, publish, distribute, sublicense, and/or sell copies 
# of the Software, and to permit persons to whom the Software is 
# furnished to do so, subject to the following conditions:
# 
# The above copyright notice and this permission notice shall be 
# included in all copies or substantial portions of the Software.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
# SOFTWARE.
#===============================================================================

import csv
import os
import sys

# BEGIN class delegated
class Delegated:
    file = None
    filename = None
    version_line = {}
    summary_lines = []
    record_lines = []
    filters = []
    cnt = {}
    
    def __init__(self, w_file):
        # init csv
        try:
            self.file = open(w_file, 'rb')
            self.file.close()
            self.filename = w_file
        except:
            raise Exception( "Could not open file %s" % (w_file) )
    ## end init
    
    def read_delegated(self):
        # init variables
        self.file = open(self.filename, 'rb')        
        self.version_line = {}
        self.summary_lines = []
        self.record_lines = []
        self.cnt = {}        
        input = csv.reader(self.file, delimiter="|")
        
        # load version line
        row = input.next() ## TODO: must skip comments
        self.version_line['version'] = row[0].strip()
        self.version_line['registry'] = row[1].strip()
        self.version_line['serial'] = row[2].strip()
        self.version_line['records'] = row[3].strip()
        self.version_line['startdate'] = row[4].strip()
        self.version_line['enddate'] = row[4].strip()
        self.version_line['UTCoffset'] = row[5].strip()
        
        # load summary lines
        row = input.next()
        while row[5].strip() == 'summary':
            summary_entry = { 'registry': row[0].strip(),
                              'type': row[2].strip(),
                              'count': row[4].strip()
                             }
            self.summary_lines.append(summary_entry)
            row = input.next()
        
        # load records
        self.cnt['all'] = 0
        self.cnt['imported'] = 0
        self.cnt['filtered'] = 0
        while row:
            try:
                record = {  'registry': row[0].strip(),
                            'cc': row[1].strip(),
                            'type': row[2].strip(),
                            'start': row[3].strip(),
                            'value': row[4].strip(),
                            'date': row[5].strip(),
                            'status': row[6].strip()
                          }
                if self._eval_filters(record):
                    self.record_lines.append(record)
                    self.cnt['imported'] = self.cnt['imported'] + 1
                else:
                    self.cnt['filtered'] = self.cnt['filtered'] + 1
                self.cnt['all'] = self.cnt['all'] + 1
                self._progress_bar(self.cnt['all'], 100)
                row = input.next()
            except StopIteration:
                print " "
                break
            except Exception as e:
                print "Could not read line %s: %s" % (self.cnt['all'], row)
                print "Exception message %s" % (e.message)
                raise
                exit(-1)
        self.file.close()
    ## end read_delegated
    
    def add_filter(self, **kwargs):
        # self.filters = []
        for key in kwargs:
            filter = {'parameter': key, 'value': kwargs[key]}
            self.filters.append(filter)
    # end add_filter
    
    def _eval_filters(self, w_record):
        result = True
        for filter in self.filters:
            try:
                parameter = filter['parameter']
                value = filter['value']
                if parameter in w_record.keys():
                    if value != w_record[parameter]:
                        result = False
                        break
            except:
                print "filter: %s" % (filter)
                raise
        return result
    # end _eval_filters
    
    # calculate amount of ip addresses
    def get_ip_count(self):
        ip_count = 0
        for record in self.record_lines:
            if record['type'] == 'ipv4':
                ip_count = ip_count + int(record['value'])
        return ip_count
    # end get ip count
    
    # reset
    def reset(self):
        self.filters = [] 
        self.version_line = {}
        self.summary_lines = []
        self.record_lines = []
        self.cnt = {}        
    # end reset
    
    # progress bar
    def _progress_bar(self, cnt, step):
        if cnt % step == 0:
            sys.stderr.write('.')
        else:
            pass    
# END class delegated

## test cases
if __name__ == "__main__":
    dlg = Delegated("data/delegated-lacnic-latest")
    dlg.add_filter(cc='BR')
    dlg.add_filter(type='ipv4')
    dlg.read_delegated()
    print "Version line: %s" % (dlg.version_line)
    #
    for line in dlg.summary_lines:
        print "\tsummary line: %s" % (line)
    #
    print "Cantidad de record lines importadas: %s" % (dlg.cnt['imported'])
    print "Cantidad de record lines no importadas: %s" % (dlg.cnt['filtered'])